<template>
  <div ref="scrollContainer" class="seamless-scroll-container">
    <!-- 静态显示模式（数据量不足时） -->
    <div v-if="!state.shouldScroll" class="static-list">
      <div v-for="(item, index) in list" :key="`static-${index}`" class="scroll-item">
        <slot :data="item" :index="index"></slot>
      </div>
    </div>

    <!-- CSS 动画滚动模式（数据量充足时） -->
    <div
      v-else
      class="scroll-wrapper"
      :style="{
        '--total-height': state.totalHeight + 'px',
        animationName: direction === 'up' ? 'scroll-up' : 'scroll-down',
        animationDuration: state.durationSec + 's',
        animationTimingFunction: 'linear',
        animationIterationCount: 'infinite',
        animationPlayState: playState
      }"
    >
      <!-- 第一个列表 -->
      <div class="scroll-list">
        <div v-for="(item, index) in list" :key="`list1-${index}`" class="scroll-item">
          <slot :data="item" :index="index"></slot>
        </div>
      </div>
      <!-- 第二个列表（紧随第一个列表之后） -->
      <div class="scroll-list">
        <div v-for="(item, index) in list" :key="`list2-${index}`" class="scroll-item">
          <slot :data="item" :index="index"></slot>
        </div>
      </div>
    </div>
  </div>
  
</template>

<script setup lang="ts">
import { ref, reactive, watch, onMounted, nextTick, toRefs } from 'vue'

// 组件属性定义
interface SeamlessScrollProps {
  list: any[] // 数据列表
  speed?: number // 滚动速度（像素/帧），默认 0.5（约 30px/s）
  itemHeight?: number // 单个项目高度（像素），0 表示自动计算
  autoStart?: boolean // 是否自动开始滚动，默认 true
  direction?: 'up' | 'down' // 滚动方向，默认 'up'
}

// 定义 props 和默认值
const props = withDefaults(defineProps<SeamlessScrollProps>(), {
  speed: 0.5,
  itemHeight: 0,
  autoStart: true,
  direction: 'up'
})

const { list, speed, itemHeight, autoStart, direction } = toRefs(props)

// 引用容器
const scrollContainer = ref<HTMLElement>()

// CSS 动画控制
const playState = ref<'running' | 'paused'>('paused')

// 渲染与计算数据
const state = reactive({
  itemHeight: 0,
  containerHeight: 0,
  visibleItemCount: 0,
  shouldScroll: false,
  totalHeight: 0,
  durationSec: 12 // 默认兜底时长
})

// 计算高度与滚动判定
const computeMetrics = () => {
  const container = scrollContainer.value
  if (!container) return

  state.containerHeight = container.clientHeight || 0

  // 优先使用外部传入高度
  if ((itemHeight.value || 0) > 0) {
    state.itemHeight = itemHeight.value as number
  } else {
    // 尝试从已渲染的第一个 .scroll-item 测量高度
    const firstItem = container.querySelector('.scroll-item') as HTMLElement | null
    state.itemHeight = firstItem?.offsetHeight || 50
  }

  const len = list.value?.length || 0
  state.totalHeight = len * state.itemHeight
  state.visibleItemCount = state.itemHeight > 0 ? Math.floor(state.containerHeight / state.itemHeight) : 0
  state.shouldScroll = len > state.visibleItemCount

  // 根据速度计算动画时长（speed: 像素/帧，约 60 帧/s）
  const pxPerSec = (speed.value || 0.5) * 60
  state.durationSec = state.totalHeight > 0 && pxPerSec > 0 ? state.totalHeight / pxPerSec : 12

  // 自动开始控制
  playState.value = state.shouldScroll && (autoStart.value ?? true) ? 'running' : 'paused'
}

// 开始/停止滚动（通过 CSS 动画的 animation-play-state 控制）
const startScroll = () => {
  if (state.shouldScroll) playState.value = 'running'
}
const stopScroll = () => {
  playState.value = 'paused'
}
const initScrollData = () => {
  nextTick(() => computeMetrics())
}

defineExpose({ startScroll, stopScroll, initScrollData })

// 监听数据与配置变化
watch([list, itemHeight], () => {
  nextTick(() => computeMetrics())
}, { deep: true })

watch(speed, () => {
  const pxPerSec = (speed.value || 0.5) * 60
  state.durationSec = state.totalHeight > 0 && pxPerSec > 0 ? state.totalHeight / pxPerSec : state.durationSec
})

watch(direction, () => {
  // 动画名通过模板绑定，方向切换后自动生效
})

onMounted(() => {
  nextTick(() => computeMetrics())
})

</script>

<style scoped>
.seamless-scroll-container {
  position: relative;
  height: 100%;
  overflow: hidden;
}

/* 包裹两个列表的容器，动画作用于该容器实现无缝滚动 */
.scroll-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  /* GPU 加速与抗闪烁处理 */
  will-change: transform;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  -webkit-perspective: 1000;
  perspective: 1000;
  transform: translate3d(0, 0, 0);
}

.scroll-list {
  width: 100%;
}

.static-list {
  width: 100%;
  height: 100%;
}

.scroll-item {
  width: 100%;
}

/* 使用 CSS 变量控制滚动距离，实现无缝循环 */
@keyframes scroll-up {
  0% { transform: translate3d(0, 0, 0); }
  100% { transform: translate3d(0, calc(-1 * var(--total-height)), 0); }
}

@keyframes scroll-down {
  0% { transform: translate3d(0, calc(-1 * var(--total-height)), 0); }
  100% { transform: translate3d(0, 0, 0); }
}
</style>
